/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { HvigorBuildConst } from '../../../../common/options/common-const.js';
import { HvigorCoreNode, Project } from '../../../../external/core/hvigor-core-node.js';
import { instanceOf } from '../../../../util/class-identify-util.js';
import { taskExecutorInst } from '../../../core/task-executor.js';
import { runTaskFromQueue } from '../../../task/core/task-runner.js';
import { union } from '../../../task/util/task-path-util.js';

import type { TaskExecuteOptions } from './execute-mode-factory.js';

/**
 * 根据不用场景创建的pileLine的抽象公共类
 *
 * @since 2022/6/20
 */
export abstract class AbstractExecutePipeline {
  protected project: Project;
  protected taskOptions: TaskExecuteOptions;
  protected shouldCheckTask = false;
  protected toRunTask: string[];

  protected constructor(project: Project, taskOptions: TaskExecuteOptions) {
    this.project = project;
    this.taskOptions = taskOptions;
    const commandToRunTasks = this.taskOptions.toRunTasks;
    this.toRunTask = commandToRunTasks.length ? commandToRunTasks : ['default'];
  }

  /**
   * 开始执行该pipeline
   */
  public async startPipeline(): Promise<void> {
    if (!this.taskOptions.isNeedSync) {
      this.recordTraceData();
    }
    await this.executeTask();
  }

  /**
   * 返回各模块所需执行的任务path
   *
   * @param nodes
   * @protected
   */
  protected findAllNeedExecuteTasksForNodes(nodes: HvigorCoreNode[]): string[] {
    const tasks: string[] = [];
    this.toRunTask.forEach((toRunTaskName) => {
      const toRunTaskPaths: string[] = nodes
        .filter((node) => node.hasTask(toRunTaskName))
        .map((node) => union(instanceOf(node, HvigorBuildConst.PROJECT_MODE) ? '' : node.getName(), toRunTaskName));
      tasks.push(...toRunTaskPaths);
    });
    return tasks;
  }

  /**
   * 初始化一个Node的打点数据
   */
  public recordTraceData(): void {
  }

  /**
   * 执行一个Mode的Task
   */
  private async executeTask(): Promise<void> {
    const needExecuteTasks: string[] = this.taskOptions.isNeedSync ? this.findPipeAllNeedExecuteSyncTasks() : [];
    needExecuteTasks.push(...this.findPipeAllNeedExecuteTasks());
    await taskExecutorInst.initTasks(needExecuteTasks);
    await runTaskFromQueue();
  }

  public abstract findPipeAllNeedExecuteSyncTasks(): string[];

  public abstract findPipeAllNeedExecuteTasks(): string[];
}
